﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RoadSystemTest
{
    public partial class frmMain : Form
    {
        const string TXT_BUTTON_START_EDIT_ROADS = "Start Edit Roads";
        const string TXT_BUTTON_END_EDIT_ROADS = "End Edit Roads";
        const string TXT_BUTTON_PAUSE_TRAFFIC = "Pause Traffic";
        const string TXT_BUTTON_CONTINUE_TRAFFIC = "Continue Traffic";
        const string TXT_BUTTON_START_TRAFFIC = "Start Traffic";
        const string TXT_BUTTON_END_TRAFFIC = "End Traffic";
        const string TXT_BUTTON_ADD_ROAD = "Add Road";
        const string TXT_BUTTON_REMOVE_ROAD = "Delete Road";
        private RoadSystem _roadSystem;
        private ITrafficObject _rootObject;

        public frmMain()
        {
            InitializeComponent();

            _roadSystem = new RoadSystem();
            _roadSystem.MouseLeftButtonDown += _roadSystem_MouseLeftButtonDown;
            _roadSystem.OnSelectObjectChanged += rs_SelectObjectChanged;
            _rootObject = null;
            lightsTime.Value = Convert.ToDecimal(_roadSystem.Lights);
        }

        void _roadSystem_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (_roadSystem.IsInEditMode)
            {
                if (_rootObject == null)
                {
                    _rootObject = new CrossRoad(new Point(e.GetPosition(null)), _roadSystem.Lights);
                    _roadSystem.AddCrossRoad((CrossRoad)_rootObject);
                }
            }
        }

        private void btnStartTraffic_MouseClick(object sender, MouseEventArgs e)
        {
            
        }

        private void rs_SelectObjectChanged(object sender, TrafficEventArgs e)
        {
            if (e.trafficObject == null)
            {
                LoadTrafficObjectPosInfo(null);
            }
            else
            {
                gbPos.Enabled = e.trafficObject == _rootObject;
                LoadTrafficObjectPosInfo(e.trafficObject);
                if (e.trafficObject is Road)
                {
                    LoadRoadInfo(e.trafficObject as Road);
                }
                else if (e.trafficObject is CrossRoad)
                {
                    LoadCrossRoadInfo(e.trafficObject as CrossRoad);
                }
            }
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            ehMain.Child = _roadSystem;
            EndTraffic();
            RefreshTabs();
        }

        private void LoadRoadInfo(Road r)
        {
            cbRightBottom.Items.Clear();
            cbLeftTop.Items.Clear();

            if (r.ForwardLane.NextLane != null)
            {
                cbRightBottom.Items.Add("<connected>");
            }
            else
            {
                cbRightBottom.Items.Add("<empty>");
                cbRightBottom.Items.Add("New Road...");
                cbRightBottom.Items.Add("New CrossRoad...");
            }
            
            cbRightBottom.SelectedIndex = 0;

            if (r.BackwardLane.NextLane != null)
            {
                cbLeftTop.Items.Add("<connected>");
            }
            else
            {
                cbLeftTop.Items.Add("<empty>");
                cbLeftTop.Items.Add("New Road...");
                cbLeftTop.Items.Add("New CrossRoad...");
            }
            
            cbLeftTop.SelectedIndex = 0;
            if (tcObjects.TabPages.IndexOf(tpEditRoad) < 0)
            {
                tcObjects.TabPages.Add(tpEditRoad);
            }
            tcObjects.TabPages.Remove(tpEditCrossRoad);
            tcObjects.SelectedTab = tpEditRoad;

            cbGenerate.Checked = _roadSystem.GetCarGenerator(r);
        }

        private void LoadCrossRoadInfo(CrossRoad cr)
        {
            if (tcObjects.TabPages.IndexOf(tpEditCrossRoad) < 0)
            {
                tcObjects.TabPages.Add(tpEditCrossRoad);
            }
            tcObjects.TabPages.Remove(tpEditRoad);
            tcObjects.SelectedTab = tpEditCrossRoad;
            if (cr.NorthRoad != null) AddNorthRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            else AddNorthRoad.Text = TXT_BUTTON_ADD_ROAD;
            if (cr.SouthRoad != null) AddSouthRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            else AddSouthRoad.Text = TXT_BUTTON_ADD_ROAD;
            if (cr.WestRoad != null) AddWestRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            else AddWestRoad.Text = TXT_BUTTON_ADD_ROAD;
            if (cr.EastRoad != null) AddEastRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            else AddEastRoad.Text = TXT_BUTTON_ADD_ROAD;
        }

        private void LoadTrafficObjectPosInfo(ITrafficObject o)
        {
            if (o == null)
            {
                tbX.Text = "";
                tbY.Text = "";
                return;
            }
            Point pos = o.GetPosition();
            tbX.Text = pos.X.ToString();
            tbY.Text = pos.Y.ToString();
            
        }

        private void RefreshTabs()
        {
            if (_roadSystem.IsInEditMode)
            {
                tcTools.TabPages.Remove(tpLights);
                tcTools.TabPages.Remove(tpCars);
                if (tcTools.TabPages.IndexOf(tpEdit) < 0)
                {
                    tcTools.TabPages.Add(tpEdit);
                }
                tcTools.SelectedTab = tpEdit;
            }
            else
            {
                tcTools.TabPages.Remove(tpEdit);
                if (tcTools.TabPages.IndexOf(tpLights) < 0)
                {
                    tcTools.TabPages.Add(tpLights);
                }
                if (tcTools.TabPages.IndexOf(tpCars) < 0)
                {
                    tcTools.TabPages.Add(tpCars);
                }
                tcTools.SelectedTab = tpLights;

            }
               
        }

        private void btnEditRoads_Click(object sender, EventArgs e)
        {
            if(_roadSystem.IsInEditMode)
            {
                EndEdit();
            }
            else
            {
                StartEdit();
            }
        }

        private void btnPauseTraffic_Click(object sender, EventArgs e)
        {
            if (_roadSystem.IsPaused)
            {
                ContinueTraffic();
            }
            else
            {
                PauseTraffic();
            }
        }

        private void btnStartTraffic_Click(object sender, EventArgs e)
        {
            if (_roadSystem.IsStarted)
            {
                EndTraffic();
            }
            else
            {
                StartTraffic();
            }
        }

        private void EndTraffic()
        {
            btnStartTraffic.Text = TXT_BUTTON_START_TRAFFIC;
            _roadSystem.EndTraffic();
            btnEditRoads.Enabled = true;
            btnPauseTraffic.Enabled = false;
        }

        private void StartTraffic()
        {
            btnStartTraffic.Text = TXT_BUTTON_END_TRAFFIC;
            _roadSystem.StartTraffic();
            btnEditRoads.Enabled = false;
            btnPauseTraffic.Enabled = true;
        }

        private void EndEdit()
        {            
            btnEditRoads.Text = TXT_BUTTON_START_EDIT_ROADS;
            _roadSystem.EndEdit();
            btnStartTraffic.Enabled = true;
            RefreshTabs();                    
        }

        private void StartEdit()
        {
            btnEditRoads.Text = TXT_BUTTON_END_EDIT_ROADS;
            _roadSystem.StartEdit();
            btnStartTraffic.Enabled = false;
            RefreshTabs();
        }

        private void PauseTraffic()
        {
            btnPauseTraffic.Text = TXT_BUTTON_CONTINUE_TRAFFIC;
            _roadSystem.PauseTraffic();
        }

        private void ContinueTraffic()
        {
            btnPauseTraffic.Text = TXT_BUTTON_PAUSE_TRAFFIC;
            _roadSystem.ContinueTraffic();
        }

        private void cbLanePoints_CheckedChanged(object sender, EventArgs e)
        {
            _roadSystem.LanePointsVisible = cbLanePoints.Checked;
        }

        private void btnPosCancel_Click(object sender, EventArgs e)
        {
            LoadTrafficObjectPosInfo(_roadSystem.SelectedObject);
        }

        private void btnPosSet_Click(object sender, EventArgs e)
        {
            Point oldPos = new Point(_roadSystem.SelectedObject.GetPosition());
            Point newPos = new Point(Convert.ToDouble(tbX.Text), Convert.ToDouble(tbY.Text));
            Point translatePos = new Point(newPos.X - oldPos.X, newPos.Y - oldPos.Y);
           // _roadSystem.SelectedObject.SetPosition(new Point(Convert.ToDouble(tbX.Text), Convert.ToDouble(tbY.Text)));
            _roadSystem.TranlateAllObjects(translatePos.X, translatePos.Y);
        }

        private void cbLeftTop_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(_roadSystem.SelectedObject == null || !(_roadSystem.SelectedObject is Road))
            {
                return;
            }
            Road selectedRoad = _roadSystem.SelectedObject as Road;
            if (cbLeftTop.SelectedIndex == 1)
            {
                // Új road a bal oldalra
                Road newRoad;
                newRoad = new Road(selectedRoad.Site, new Point(0, 0));
                _roadSystem.AddRoad(newRoad);
                selectedRoad.ConnectWestSouthRoad(newRoad);
            }
            else if (cbLeftTop.SelectedIndex == 2)
            {
                // Új crossroad a bal oldalra
                CrossRoad newCRoad = new CrossRoad(new Point(0, 0), _roadSystem.Lights);
                _roadSystem.AddCrossRoad(newCRoad);
                if (selectedRoad.Site == Sites.Horizontal)
                {
                    newCRoad.ConnectEastRoad(selectedRoad);
                    newCRoad.SetPosition(new Point(selectedRoad.GetPosition().X - 250, selectedRoad.GetPosition().Y - 50));
                }
                else
                {
                    newCRoad.ConnectSouthRoad(selectedRoad);
                    newCRoad.SetPosition(new Point(selectedRoad.GetPosition().X - 50, selectedRoad.GetPosition().Y + 150));
                }
            }
        }

        private void cbRightBottom_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (_roadSystem.SelectedObject == null || !(_roadSystem.SelectedObject is Road))
            {
                return;
            }
            Road selectedRoad = _roadSystem.SelectedObject as Road;
            if (cbRightBottom.SelectedIndex == 1)
            {
                // Új road a jobb oldalra
                Road newRoad;
                newRoad = new Road(selectedRoad.Site, new Point(0, 0));
                _roadSystem.AddRoad(newRoad);
                selectedRoad.ConnectEastNorthRoad(newRoad);
            }
            else if (cbRightBottom.SelectedIndex == 2)
            {
                // Új crossroad a jobb oldalra
                CrossRoad newCRoad = new CrossRoad(new Point(0, 0), _roadSystem.Lights);
                _roadSystem.AddCrossRoad(newCRoad);
                if (selectedRoad.Site == Sites.Horizontal)
                {
                    newCRoad.ConnectWestRoad(selectedRoad);
                    newCRoad.SetPosition(new Point(selectedRoad.GetPosition().X + 150, selectedRoad.GetPosition().Y - 50));
                }
                else
                {
                    newCRoad.ConnectNorthRoad(selectedRoad);
                    newCRoad.SetPosition(new Point(selectedRoad.GetPosition().X - 50, selectedRoad.GetPosition().Y - 250));
                }
            }
        }

        private void cbGenerate_CheckedChanged(object sender, EventArgs e)
        {
            if (_roadSystem.SelectedObject == null || !(_roadSystem.SelectedObject is Road))
            {
                return;
            }
            Road selectedRoad = _roadSystem.SelectedObject as Road;
            _roadSystem.SetCarGenerator(selectedRoad, cbGenerate.Checked);
        }

        //Beállítja a lámpa váltásai között lévő időközöket
        private void lightsOK_Button_Click(object sender, EventArgs e)
        {
            _roadSystem.SetLightInterval(Convert.ToInt32(lightsTime.Value));
        }


        //Kereszteződéshez utakat hozzáadó/letörlő metódusok
        //A másik három lényegében ugyanez
        private void AddNorthRoad_Click(object sender, EventArgs e)
        {
            CrossRoad selectedCRoad = _roadSystem.SelectedObject as CrossRoad;
            //Ha nincs út, akkor létrehoz egyet, és hozzákapcsolja
            if (selectedCRoad.NorthRoad == null)
            {
                Road newRoad = new Road(Sites.Vertical, new Point(selectedCRoad.GetPosition().X + 50, selectedCRoad.GetPosition().Y - 150));
                selectedCRoad.ConnectNorthRoad(newRoad);
                _roadSystem.AddRoad(newRoad);
                AddNorthRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            }
            //Ha van út, akkor megszünteti a kapcsolatot és törli az utat
            //de csak akkor, ha annak az útnak nincs semmi a másik oldalán
            else
            {
                Road n = selectedCRoad.NorthRoad;
                if (n.ForwardLane.NextLane == null)
                {
                    selectedCRoad.DisconnectNorthRoad();
                    _roadSystem.RemoveRoad(n);
                    AddNorthRoad.Text = TXT_BUTTON_ADD_ROAD;
                }
            }
        }

        private void AddSouthRoad_Click(object sender, EventArgs e)
        {
            CrossRoad selectedCRoad = _roadSystem.SelectedObject as CrossRoad;
            if (selectedCRoad.SouthRoad == null)
            {
                Road newRoad = new Road(Sites.Vertical, new Point(selectedCRoad.GetPosition().X + 50, selectedCRoad.GetPosition().Y + 250));
                selectedCRoad.ConnectSouthRoad(newRoad);
                _roadSystem.AddRoad(newRoad);
                AddSouthRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            }
            else
            {
                Road n = selectedCRoad.SouthRoad;
                if (n.BackwardLane.NextLane == null)
                {
                    selectedCRoad.DisconnectSouthRoad();
                    _roadSystem.RemoveRoad(n);
                    AddSouthRoad.Text = TXT_BUTTON_ADD_ROAD;
                }
            }
        }

        private void AddWestRoad_Click(object sender, EventArgs e)
        {
            CrossRoad selectedCRoad = _roadSystem.SelectedObject as CrossRoad;
            if (selectedCRoad.WestRoad == null)
            {
                Road newRoad = new Road(Sites.Horizontal, new Point(selectedCRoad.GetPosition().X - 150, selectedCRoad.GetPosition().Y + 50));
                selectedCRoad.ConnectWestRoad(newRoad);
                _roadSystem.AddRoad(newRoad);
                AddWestRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            }
            else
            {
                Road n = selectedCRoad.WestRoad;
                if (n.BackwardLane.NextLane == null)
                {
                    selectedCRoad.DisconnectWestRoad();
                    _roadSystem.RemoveRoad(n);
                    AddWestRoad.Text = TXT_BUTTON_ADD_ROAD;
                }
            }
        }

        private void AddEastRoad_Click(object sender, EventArgs e)
        {
            CrossRoad selectedCRoad = _roadSystem.SelectedObject as CrossRoad;
            if (selectedCRoad.EastRoad == null)
            {
                Road newRoad = new Road(Sites.Horizontal, new Point(selectedCRoad.GetPosition().X + 250, selectedCRoad.GetPosition().Y + 50));
                selectedCRoad.ConnectEastRoad(newRoad);
                _roadSystem.AddRoad(newRoad);
                AddEastRoad.Text = TXT_BUTTON_REMOVE_ROAD;
            }
            else
            {
                Road n = selectedCRoad.EastRoad;
                if (n.ForwardLane.NextLane == null)
                {
                    selectedCRoad.DisconnectEastRoad();
                    _roadSystem.RemoveRoad(n);
                    AddEastRoad.Text = TXT_BUTTON_ADD_ROAD;
                }
            }
        }
    }
}
